Loading up the data for some preliminary analyses of the binary
climb/no-climb categories.
Load data
Note that the indices are all caps, and the linear measurements have
lowercase letters after the first.
dat <- read_sheet("https://docs.google.com/spreadsheets/d/1-eknhyZ1JNnXqhg2kViyzVntC8NGZvILQX-aQQb1Jvk/edit#gid=325036460", na = c("NA", "?", "")) %>%
select(!NOTES) %>%
# Recode Ordinal Rankings
mutate(Loc_Ord = case_when(Loc_mode_Ordinal == "G" ~ 1,
Loc_mode_Ordinal == "A" ~ 2,
Loc_mode_Ordinal == "Sc" ~ 3,
Loc_mode_Ordinal == "T" ~ 4,
Loc_mode_Ordinal == "Is" ~ 5,
Loc_mode_Ordinal == "Sf" ~ 5,
Loc_mode_Ordinal == "Ss" ~ 6,
TRUE ~ NA),
Loc_Ord = as.ordered(Loc_Ord),
Loc_bin = case_when(Loc_mode_Bindary == "Ground" ~ 0,
Loc_mode_Bindary == "Tree" ~ 1,
TRUE ~ NA
),
# Loc_bin = as.factor(Loc_bin),
Loc_mode_Categorical = as.factor(Loc_mode_Categorical),
log_Mass = log(Mass_grams)) %>%
relocate(Loc_bin, .after = Loc_mode_Bindary) %>%
relocate(Loc_Ord, .after = Loc_mode_Ordinal) %>%
relocate(log_Mass, .before = Skl) %>%
#Calculate Ratios
mutate(SI = Sh / Sl, # Scapular Index
HRI = Hsw / Hl, # Humeral Robustness Index
HPI = Hpw / Hl, # Humeral Proximal Index
HEB = Hdw / Hl, # Humeral Epicondyle Breadth
HHRI = Hhl / Hl, # Humeral Head Robustness Index
HHW = Hhw / Hhl, # Humeral Head Shape Index
DI = Hdcw / Hsw, # Deltopectoral Crest Index
OLI = Uol / Ul, # Olecranon Process Length Index
BI = Rl / Hl, # Brachial Index
IM = (Hl+Ul)/(Fl+Tl), # Intermembral Index
PRTI = Mcl/(Hl+Rl), # Palm Robustness Index
MRI = Mcw / Mcl, # Metacarpal Robustness
MANUS = Ppl / Mcl, # MANUS index
MANUS2 = (Ppl+Ipl)/Mcl, # MANUS index with intermed. phalanx
IRI = Fgh / Fl, # Gluteal Index
FRI = Fsw / Fl, # Femoral Robustness
FEB = Fdw / Fl, # Femoral Epicondyle Breadth
CI = Tl / Fl, # Crural Index
TRI = Tmw / Tl, # Tibial Robustness Index
#ANR = Anl / Al, # Astragular Neck Robustness Index
#CAR = Cal / Cl, # Calcaneal Robustness Index
IRI = Il / Pel, # Illium Robustness Index
PR = Il / Isl, # Pelvic Index
PES = Pppl / Mtl, # PES INdex
PES2 = (Pppl+Pipl)/Mtl # PES with intermediate Phalanx
) %>%
mutate_at(vars(17:71), log) %>%
mutate_at(vars(16:93), scale2)
✔ Reading from Master_Data.
✔ Range all data.
What does the missing data look like?
You can scroll through the table below
n = nrow(dat)
dat %>% select(16:93) %>%
summarise_all((~ sum(is.na(.)))) %>%
mutate_if(is.double, ~ n - .) %>%
pivot_longer(everything(), names_to = "measurement", values_to = "count_missing") %>% arrange(desc(count_missing), measurement) %>%
mutate(percent_missing = round(count_missing / n, digits = 3)) %>%
kbl(caption = "Percentage of Missing Data") %>%
kable_classic(full_width = F, html_font = "Cambria") %>%
scroll_box(width = "500px", height = "200px")
Percentage of Missing Data
| measurement |
count_missing |
percent_missing |
| Pdpw |
324 |
0.773 |
| Pipw |
278 |
0.663 |
| Pdpl |
277 |
0.661 |
| Dpw |
263 |
0.628 |
| Jl |
249 |
0.594 |
| Anl |
239 |
0.570 |
| Atw |
239 |
0.570 |
| Cal |
239 |
0.570 |
| Ccw |
238 |
0.568 |
| Csw |
238 |
0.568 |
| Ctl |
238 |
0.568 |
| Ctw |
238 |
0.568 |
| Al |
237 |
0.566 |
| Pppw |
230 |
0.549 |
| Skl |
228 |
0.544 |
| Mtw |
223 |
0.532 |
| Ipw |
217 |
0.518 |
| Dpl |
216 |
0.516 |
| PES2 |
194 |
0.463 |
| Pipl |
193 |
0.461 |
| Fbdw |
189 |
0.451 |
| Fbmw |
187 |
0.446 |
| Fgh |
187 |
0.446 |
| Fhd |
187 |
0.446 |
| HHRI |
185 |
0.442 |
| HHW |
185 |
0.442 |
| Hhl |
185 |
0.442 |
| Hhw |
185 |
0.442 |
| Ppw |
158 |
0.377 |
| Cl |
154 |
0.368 |
| Fbpw |
153 |
0.365 |
| MRI |
152 |
0.363 |
| Mcw |
152 |
0.363 |
| DI |
144 |
0.344 |
| Hdcw |
144 |
0.344 |
| Tdw |
141 |
0.337 |
| Tpw |
138 |
0.329 |
| Fbl |
137 |
0.327 |
| IRI |
137 |
0.327 |
| Isl |
137 |
0.327 |
| PR |
137 |
0.327 |
| Pel |
137 |
0.327 |
| Il |
136 |
0.325 |
| HPI |
135 |
0.322 |
| Hpw |
135 |
0.322 |
| Ipl |
117 |
0.279 |
| MANUS2 |
117 |
0.279 |
| PES |
95 |
0.227 |
| Pppl |
94 |
0.224 |
| Mtl |
88 |
0.210 |
| MANUS |
23 |
0.055 |
| Ppl |
23 |
0.055 |
| Mcl |
17 |
0.041 |
| PRTI |
17 |
0.041 |
| log_Mass |
10 |
0.024 |
| TRI |
3 |
0.007 |
| Tmw |
3 |
0.007 |
| CI |
2 |
0.005 |
| FEB |
2 |
0.005 |
| Fdw |
2 |
0.005 |
| IM |
2 |
0.005 |
| Tl |
2 |
0.005 |
| FRI |
1 |
0.002 |
| Fl |
1 |
0.002 |
| Fsw |
1 |
0.002 |
| SI |
1 |
0.002 |
| Sh |
1 |
0.002 |
| Sl |
1 |
0.002 |
| BI |
0 |
0.000 |
| HEB |
0 |
0.000 |
| HRI |
0 |
0.000 |
| Hdw |
0 |
0.000 |
| Hl |
0 |
0.000 |
| Hsw |
0 |
0.000 |
| OLI |
0 |
0.000 |
| Rl |
0 |
0.000 |
| Ul |
0 |
0.000 |
| Uol |
0 |
0.000 |
Binary Climb/No Climb Models
Preliminary data analysis, looping over all of the variables to see
which ones do a good job predicting the binary tree vs. no-tree
categorization
These are very preliminary data, and the results will become more
Here are all the model plots. On the y axis, 1 is TREE, 0 is NO TREE.
The x axis is the phenotype, mean centered on 0 and scaled to a standard
deviation of 1. All of the linear measurements are log transformed prior
to mean-centering. All the models include log_mass as a variable,
meaning that they are “size corrected”
representations of the effect of the phenotype on climbing. What we are
looking for is a slope that ranges across the whole y axis, meaning that
it touches the 1 and 0, and has a steep slope (either up or down). To
interpret, look at the 3rd plot, Hl. As Hl increases,
the probability of being TREE increases.
Here are some standouts: (remember, these are log-transformed
and size-corrected effect sizes)
- humeral length (Hl)
- Olecranon length (Uol)
- Ulnar length (Ul)
- Radius length (Rl)
- Femur length (Fl)
- Proximal phalanx of the manus length (Ppl)
- Intermediate phalanx of the manus length (Ppl)
- Olecranon Length Index (OLI)
- MANUS and MANUS2 indices (#2 includes the intermediate phalanx)
- PES and PES2
for(i in fit_list2){
plot <- plot(conditional_effects(i), plot=F, points = T)[[1]]
print(plot)
}











































































LS0tCnRpdGxlOiAiRmlyc3QgR2xpbXBzZSBvZiBEYXRhIgpvdXRwdXQ6IGh0bWxfZG9jdW1lbnQKLS0tCgpMb2FkaW5nIHVwIHRoZSBkYXRhIGZvciBzb21lIHByZWxpbWluYXJ5IGFuYWx5c2VzIG9mIHRoZSBiaW5hcnkgY2xpbWIvbm8tY2xpbWIgY2F0ZWdvcmllcy4KCmBgYHtyIG1lc3NhZ2UgPSBGQUxTRSwgd2FybmluZz1GQUxTRSwgaW5jbHVkZSA9IEZBTFNFfQpwYWNtYW46OnBfbG9hZCh0aWR5dmVyc2UsIGdvb2dsZXNoZWV0czQsIGJybXMsIGNtZHN0YW5yLCBrYWJsZUV4dHJhKQpvcHRpb25zKGJybXMuYmFja2VuZCA9ICJjbWRzdGFuciIpCgpzY2FsZTIgPC0gZnVuY3Rpb24oeCwgbmEucm0gPSBUUlVFKSAoeCAtIG1lYW4oeCwgbmEucm0gPSBUUlVFKSkgLyBzZCh4LCBuYS5ybSkKYGBgCgojIyMjIExvYWQgZGF0YSAgCgpOb3RlIHRoYXQgdGhlIGluZGljZXMgYXJlIGFsbCBjYXBzLCBhbmQgdGhlIGxpbmVhciBtZWFzdXJlbWVudHMgaGF2ZSBsb3dlcmNhc2UgbGV0dGVycyBhZnRlciB0aGUgZmlyc3QuCgpgYGB7cn0KZGF0IDwtIHJlYWRfc2hlZXQoImh0dHBzOi8vZG9jcy5nb29nbGUuY29tL3NwcmVhZHNoZWV0cy9kLzEtZWtuaHlaMUpOblhxaGcya1ZpeXpWbnRDOE5HWnZJTFFYLWFRUWIxSnZrL2VkaXQjZ2lkPTMyNTAzNjQ2MCIsIG5hID0gYygiTkEiLCAiPyIsICIiKSkgJT4lCiAgc2VsZWN0KCFOT1RFUykgJT4lIAojIFJlY29kZSBPcmRpbmFsIFJhbmtpbmdzCiAgbXV0YXRlKExvY19PcmQgPSBjYXNlX3doZW4oTG9jX21vZGVfT3JkaW5hbCA9PSAiRyIgfiAxLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgIExvY19tb2RlX09yZGluYWwgPT0gIkEiIH4gMiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICBMb2NfbW9kZV9PcmRpbmFsID09ICJTYyIgfiAzLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgIExvY19tb2RlX09yZGluYWwgPT0gIlQiIH4gNCwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICBMb2NfbW9kZV9PcmRpbmFsID09ICJJcyIgfiA1LAogICAgICAgICAgICAgICAgICAgICAgICAgICAgIExvY19tb2RlX09yZGluYWwgPT0gIlNmIiB+IDUsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgTG9jX21vZGVfT3JkaW5hbCA9PSAiU3MiIH4gNiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICBUUlVFIH4gTkEpLAogICAgICAgICBMb2NfT3JkID0gYXMub3JkZXJlZChMb2NfT3JkKSwKICAgICAgICAgTG9jX2JpbiA9IGNhc2Vfd2hlbihMb2NfbW9kZV9CaW5kYXJ5ID09ICJHcm91bmQiIH4gMCwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICBMb2NfbW9kZV9CaW5kYXJ5ID09ICJUcmVlIiB+IDEsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgVFJVRSB+IE5BCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgKSwKICAgICAgICAjIExvY19iaW4gPSBhcy5mYWN0b3IoTG9jX2JpbiksCiAgICAgICAgIExvY19tb2RlX0NhdGVnb3JpY2FsID0gYXMuZmFjdG9yKExvY19tb2RlX0NhdGVnb3JpY2FsKSwKICAgICAgICAgbG9nX01hc3MgPSBsb2coTWFzc19ncmFtcykpICU+JSAKICAgIHJlbG9jYXRlKExvY19iaW4sIC5hZnRlciA9IExvY19tb2RlX0JpbmRhcnkpICU+JSAKICByZWxvY2F0ZShMb2NfT3JkLCAuYWZ0ZXIgPSBMb2NfbW9kZV9PcmRpbmFsKSAlPiUgCiAgcmVsb2NhdGUobG9nX01hc3MsIC5iZWZvcmUgPSBTa2wpICU+JSAKI0NhbGN1bGF0ZSBSYXRpb3MKICBtdXRhdGUoU0kgPSBTaCAvIFNsLCAgICAgICAgICAgICAjIFNjYXB1bGFyIEluZGV4CiAgICAgICAgIEhSSSA9IEhzdyAvIEhsLCAgICAgICAgICAgIyBIdW1lcmFsIFJvYnVzdG5lc3MgSW5kZXgKICAgICAgICAgSFBJID0gSHB3IC8gSGwsICAgICAgICAgICAjIEh1bWVyYWwgUHJveGltYWwgSW5kZXgKICAgICAgICAgSEVCID0gSGR3IC8gSGwsICAgICAgICAgICAjIEh1bWVyYWwgRXBpY29uZHlsZSBCcmVhZHRoCiAgICAgICAgIEhIUkkgPSBIaGwgLyBIbCwgICAgICAgICAgIyBIdW1lcmFsIEhlYWQgUm9idXN0bmVzcyBJbmRleAogICAgICAgICBISFcgPSBIaHcgLyBIaGwsICAgICAgICAgICMgSHVtZXJhbCBIZWFkIFNoYXBlIEluZGV4CiAgICAgICAgIERJID0gSGRjdyAvIEhzdywgICAgICAgICAgIyBEZWx0b3BlY3RvcmFsIENyZXN0IEluZGV4CiAgICAgICAgIE9MSSA9IFVvbCAvIFVsLCAgICAgICAgICAgIyBPbGVjcmFub24gUHJvY2VzcyBMZW5ndGggSW5kZXgKICAgICAgICAgQkkgPSBSbCAvIEhsLCAgICAgICAgICAgICAjIEJyYWNoaWFsIEluZGV4CiAgICAgICAgIElNID0gKEhsK1VsKS8oRmwrVGwpLCAgICAgIyBJbnRlcm1lbWJyYWwgSW5kZXgKICAgICAgICAgUFJUSSA9IE1jbC8oSGwrUmwpLCAgICAgICAjIFBhbG0gUm9idXN0bmVzcyBJbmRleAogICAgICAgICBNUkkgPSBNY3cgLyBNY2wsICAgICAgICAgICMgTWV0YWNhcnBhbCBSb2J1c3RuZXNzCiAgICAgICAgIE1BTlVTID0gUHBsIC8gTWNsLCAgICAgICAgIyBNQU5VUyBpbmRleAogICAgICAgICBNQU5VUzIgPSAoUHBsK0lwbCkvTWNsLCAgICMgTUFOVVMgaW5kZXggd2l0aCBpbnRlcm1lZC4gcGhhbGFueAogICAgICAgICBJUkkgPSBGZ2ggLyBGbCwgICAgICAgICAgICMgR2x1dGVhbCBJbmRleAogICAgICAgICBGUkkgPSBGc3cgLyBGbCwgICAgICAgICAgICMgRmVtb3JhbCBSb2J1c3RuZXNzCiAgICAgICAgIEZFQiA9IEZkdyAvIEZsLCAgICAgICAgICAgIyBGZW1vcmFsIEVwaWNvbmR5bGUgQnJlYWR0aAogICAgICAgICBDSSA9IFRsIC8gRmwsICAgICAgICAgICAgICMgQ3J1cmFsIEluZGV4CiAgICAgICAgIFRSSSA9IFRtdyAvIFRsLCAgICAgICAgICAgIyBUaWJpYWwgUm9idXN0bmVzcyBJbmRleAogICAgICAgICAjQU5SID0gQW5sIC8gQWwsICAgICAgICAgICMgQXN0cmFndWxhciBOZWNrIFJvYnVzdG5lc3MgSW5kZXgKICAgICAgICAgI0NBUiA9IENhbCAvIENsLCAgICAgICAgICAjIENhbGNhbmVhbCBSb2J1c3RuZXNzIEluZGV4CiAgICAgICAgIElSSSA9IElsIC8gUGVsLCAgICAgICAgICAgIyBJbGxpdW0gUm9idXN0bmVzcyBJbmRleAogICAgICAgICBQUiA9IElsIC8gSXNsLCAgICAgICAgICAgICMgUGVsdmljIEluZGV4CiAgICAgICAgIFBFUyA9IFBwcGwgLyBNdGwsICAgICAgICAgIyBQRVMgSU5kZXgKICAgICAgICAgUEVTMiA9IChQcHBsK1BpcGwpL010bCAgICAjIFBFUyB3aXRoIGludGVybWVkaWF0ZSBQaGFsYW54CiAgICAgICAgICkgJT4lIAogIG11dGF0ZV9hdCh2YXJzKDE3OjcxKSwgbG9nKSAlPiUgCiAgbXV0YXRlX2F0KHZhcnMoMTY6OTMpLCBzY2FsZTIpCmBgYApXaGF0IGRvZXMgdGhlIG1pc3NpbmcgZGF0YSBsb29rIGxpa2U/ICAKWW91IGNhbiBzY3JvbGwgdGhyb3VnaCB0aGUgdGFibGUgYmVsb3cgIAoKYGBge3IgfQpuID0gbnJvdyhkYXQpCgpkYXQgJT4lIHNlbGVjdCgxNjo5MykgJT4lIAogIHN1bW1hcmlzZV9hbGwoKH4gc3VtKGlzLm5hKC4pKSkpICU+JSAKICBtdXRhdGVfaWYoaXMuZG91YmxlLCB+IG4gLSAuKSAlPiUgCiAgcGl2b3RfbG9uZ2VyKGV2ZXJ5dGhpbmcoKSwgbmFtZXNfdG8gPSAibWVhc3VyZW1lbnQiLCB2YWx1ZXNfdG8gPSAiY291bnRfbWlzc2luZyIpICU+JSBhcnJhbmdlKGRlc2MoY291bnRfbWlzc2luZyksIG1lYXN1cmVtZW50KSAlPiUgCiAgbXV0YXRlKHBlcmNlbnRfbWlzc2luZyA9IHJvdW5kKGNvdW50X21pc3NpbmcgLyBuLCBkaWdpdHMgPSAzKSkgJT4lIAogIGtibChjYXB0aW9uID0gIlBlcmNlbnRhZ2Ugb2YgTWlzc2luZyBEYXRhIikgJT4lIAogIGthYmxlX2NsYXNzaWMoZnVsbF93aWR0aCA9IEYsIGh0bWxfZm9udCA9ICJDYW1icmlhIikgJT4lIAogIHNjcm9sbF9ib3god2lkdGggPSAiNTAwcHgiLCBoZWlnaHQgPSAiMjAwcHgiKQpgYGAKCgojIyMjIEJpbmFyeSBDbGltYi9ObyBDbGltYiBNb2RlbHMKClByZWxpbWluYXJ5IGRhdGEgYW5hbHlzaXMsIGxvb3Bpbmcgb3ZlciBhbGwgb2YgdGhlIHZhcmlhYmxlcyB0byBzZWUgd2hpY2ggb25lcyBkbyBhIGdvb2Qgam9iIHByZWRpY3RpbmcgdGhlIGJpbmFyeSB0cmVlIHZzLiBuby10cmVlIGNhdGVnb3JpemF0aW9uCgpUaGVzZSBhcmUgdmVyeSBwcmVsaW1pbmFyeSBkYXRhLCBhbmQgdGhlIHJlc3VsdHMgd2lsbCBiZWNvbWUgbW9yZSAKCmBgYHtyIG1lc3NhZ2UgPSBGQUxTRSwgd2FybmluZz1GQUxTRSwgaW5jbHVkZSA9IEZBTFNFLCBjYWNoZT1UUlVFfQojaW5pdGlhbCBmaXQKbW0gPC0gYnJtKAogICNMb2NfYmluIH4gU2wgKyBsb2dfTWFzcyArICgxIHwgR2VudXNfc3BlY2llcyksCiAgTG9jX2JpbiB+IFNsICsgbG9nX01hc3MsCiAgICAgICAgICAgZmFtaWx5ID0gYmVybm91bGxpKCksCiAgICAgICAgICAgZGF0YSA9IGRhdCwgcmVmcmVzaCA9IDApCmBgYAoKCmBgYHtyIG1lc3NhZ2UgPSBGQUxTRSwgd2FybmluZz1GQUxTRSwgaW5jbHVkZSA9IEZBTFNFLCBjYWNoZT1UUlVFfQoKdmFyaXMgPC0gY29sbmFtZXMoZGF0KVsxOTo5M10KCmZpdF9saXN0IDwtIHZlY3Rvcihtb2RlID0ibGlzdCIsIGxlbmd0aCA9IDc3KQoKZm9yKGkgaW4gdmFyaXMpewogIGZpdF9saXN0W1tpXV08LSB1cGRhdGUobW0sCiAgICAgICAgICAgICAgICAgICAgICAgICAjZm9ybXVsYT0ocGFzdGUwKCJMb2NfYmluIH4iLCBpLCAiK2xvZ19NYXNzKygxfEdlbnVzX3NwZWNpZXMpIikpLAogICAgICAgICAgICAgICAgICAgICAgICAgZm9ybXVsYT0ocGFzdGUwKCJMb2NfYmluIH4iLCBpLCAiK2xvZ19NYXNzIikpLAogICAgICAgICAgICAgICAgICAgICAgICAgZmFtaWx5ID0gYmVybm91bGxpKCksCiAgICAgICAgICAgICAgICAgICAgICAgICBuZXdkYXRhPWRhdCwKICAgICAgICAgICAgICAgICAgICAgICAgIHJlZnJlc2ggPSAwCiAgICAgICAgICAgICAgICAgICAgICAgICApIAp9CgpmaXRfbGlzdDIgPC0gZml0X2xpc3RbNzg6MTUyXQpybShmaXRfbGlzdCkKYGBgCgpIZXJlIGFyZSBhbGwgdGhlIG1vZGVsIHBsb3RzLiBPbiB0aGUgeSBheGlzLCAxIGlzIFRSRUUsIDAgaXMgTk8gVFJFRS4gVGhlIHggYXhpcyBpcyB0aGUgcGhlbm90eXBlLCBtZWFuIGNlbnRlcmVkIG9uIDAgYW5kIHNjYWxlZCB0byBhIHN0YW5kYXJkIGRldmlhdGlvbiBvZiAxLiBBbGwgb2YgdGhlIGxpbmVhciBtZWFzdXJlbWVudHMgYXJlIGxvZyB0cmFuc2Zvcm1lZCBwcmlvciB0byBtZWFuLWNlbnRlcmluZy4gQWxsIHRoZSBtb2RlbHMgaW5jbHVkZSBsb2dfbWFzcyBhcyBhIHZhcmlhYmxlLCBtZWFuaW5nIHRoYXQgdGhleSBhcmUgIioqKnNpemUgY29ycmVjdGVkKioqIiByZXByZXNlbnRhdGlvbnMgb2YgdGhlIGVmZmVjdCBvZiB0aGUgcGhlbm90eXBlIG9uIGNsaW1iaW5nLiBXaGF0IHdlIGFyZSBsb29raW5nIGZvciBpcyBhIHNsb3BlIHRoYXQgcmFuZ2VzIGFjcm9zcyB0aGUgd2hvbGUgeSBheGlzLCBtZWFuaW5nIHRoYXQgaXQgdG91Y2hlcyB0aGUgMSBhbmQgMCwgYW5kIGhhcyBhIHN0ZWVwIHNsb3BlIChlaXRoZXIgdXAgb3IgZG93bikuIFRvIGludGVycHJldCwgbG9vayBhdCB0aGUgM3JkIHBsb3QsICoqSGwqKi4gQXMgSGwgaW5jcmVhc2VzLCB0aGUgcHJvYmFiaWxpdHkgb2YgYmVpbmcgKipUUkVFKiogaW5jcmVhc2VzLiAKCkhlcmUgYXJlIHNvbWUgc3RhbmRvdXRzOiAoKipyZW1lbWJlciwgdGhlc2UgYXJlIGxvZy10cmFuc2Zvcm1lZCBhbmQgc2l6ZS1jb3JyZWN0ZWQgZWZmZWN0IHNpemVzKiopICAKCi0gaHVtZXJhbCBsZW5ndGggKEhsKSAgCi0gT2xlY3Jhbm9uIGxlbmd0aCAoVW9sKSAgCi0gVWxuYXIgbGVuZ3RoIChVbCkgIAotIFJhZGl1cyBsZW5ndGggKFJsKSAgCi0gRmVtdXIgbGVuZ3RoIChGbCkgIAotIFByb3hpbWFsIHBoYWxhbnggb2YgdGhlIG1hbnVzIGxlbmd0aCAoUHBsKSAgCi0gSW50ZXJtZWRpYXRlIHBoYWxhbnggb2YgdGhlIG1hbnVzIGxlbmd0aCAoUHBsKSAgCi0gT2xlY3Jhbm9uIExlbmd0aCBJbmRleCAoT0xJKSAgCi0gTUFOVVMgYW5kIE1BTlVTMiBpbmRpY2VzICgjMiBpbmNsdWRlcyB0aGUgaW50ZXJtZWRpYXRlIHBoYWxhbngpIAotIFBFUyBhbmQgUEVTMiAgCgpgYGB7ciBtZXNzYWdlID0gRkFMU0UsIHdhcm5pbmc9RkFMU0UsIGNhY2hlPVRSVUV9CmZvcihpIGluIGZpdF9saXN0Mil7CiBwbG90IDwtIHBsb3QoY29uZGl0aW9uYWxfZWZmZWN0cyhpKSwgcGxvdD1GLCBwb2ludHMgPSBUKVtbMV1dCiBwcmludChwbG90KQp9CgpgYGAK